package com.navinfo.platform.trip.common.util;

import com.google.protobuf.ByteString;
import com.navinfo.opentsp.platform.location.protocol.common.LCLocationData;
import com.navinfo.opentsp.platform.location.protocol.common.LCVehicleStatusData;
import com.navinfo.opentsp.platform.location.protocol.common.RealTimeDataPb;
import com.navinfo.platform.trip.common.pojo.Point0200;
import com.navinfo.platform.trip.common.pojo.Point0F37;
import com.navinfo.platform.trip.common.pojo.PointProtocol;
import com.navinfo.platform.trip.common.enums.ProtocolEnum;

import java.util.List;
import java.util.Optional;

import static com.navinfo.opentsp.platform.location.protocol.common.LCStatusType.StatusType.*;

/**
 * Point的工具类
 * @author: web
 * @date: 2020-04-21
 **/
public class PointUtils {
    /**
     * 公共轨迹协议转换为Point0200
     * @return Point0200
     */
    public static Point0200 toPoint0200(PointProtocol pointProtocol){
        Point0200 point0200 = null;
        if(null!=pointProtocol && ProtocolEnum.LOCATION.equals(pointProtocol.getProtocol())){
            point0200 = new Point0200();
            point0200.setTid(pointProtocol.getTid());
            point0200.setTripId(pointProtocol.getTripId());
            point0200.setProtocol(pointProtocol.getProtocol());
            point0200.setGpsTime(pointProtocol.getGpsTime());
            point0200.setSpeedKmh(pointProtocol.getSpeedKmh());
            point0200.setLongitude(pointProtocol.getLongitude());
            point0200.setLatitude(pointProtocol.getLatitude());
            point0200.setOriginalLat(pointProtocol.getOriginalLat());
            point0200.setOriginalLng(pointProtocol.getOriginalLng());
            point0200.setHeight(pointProtocol.getHeight());
            point0200.setDirection(pointProtocol.getDirection());
            point0200.setRotation(pointProtocol.getRotation());
            point0200.setAccPedalPos(pointProtocol.getAccPedalPos());
            point0200.setClutchSwitch(pointProtocol.getClutchSwitch());
            point0200.setEngineOutputTorque(pointProtocol.getEngineOutputTorque());
            point0200.setFuelConsumptionRate(pointProtocol.getFuelConsumptionRate());
            point0200.setRealTimeOilConsumption(pointProtocol.getRealTimeOilConsumption());

            //0200特有（原始类型修饰）
            point0200.setAccStatus(pointProtocol.getAccStatus());
            point0200.setCurveStatus(pointProtocol.getCurveStatus());
            point0200.setCruiseControl(pointProtocol.getCruiseControl());
            point0200.setHandBrakeStatus(pointProtocol.getHandBrakeStatus());
            point0200.setSlideNeutralStatus(pointProtocol.getSlideNeutralStatus());
            point0200.setSharpTurningStatus(pointProtocol.getSharpTurningStatus());
            point0200.setSlamAcceleratorStatus(pointProtocol.getSlamAcceleratorStatus());
            point0200.setRapidAccelerationStatus(pointProtocol.getRapidAccelerationStatus());
            point0200.setRapidDecelerationStatus(pointProtocol.getRapidDecelerationStatus());

            //0200特有（包装类型修饰）
            point0200.setGpsMileage(Optional.ofNullable(pointProtocol.getGpsMileage()).orElse(0.0));
            point0200.setEcuMileage(Optional.ofNullable(pointProtocol.getEcuMileage()).orElse(0.0));
            point0200.setMeterMileage(Optional.ofNullable(pointProtocol.getMeterMileage()).orElse(0.0));
            point0200.setIntegralMileage(Optional.ofNullable(pointProtocol.getIntegralMileage()).orElse(0.0));
            point0200.setStandardMileage(Optional.ofNullable(pointProtocol.getStandardMileage()).orElse(0.0f));
            point0200.setIntegralFuelCons(Optional.ofNullable(pointProtocol.getIntegralFuelCons()).orElse(0.0));
            point0200.setStandardFuelCons(Optional.ofNullable(pointProtocol.getStandardFuelCons()).orElse(0.0f));
            point0200.setTotalFuelCons(Optional.ofNullable(pointProtocol.getTotalFuelCons()).orElse(0.0));
            point0200.setOilPercentage(Optional.ofNullable(pointProtocol.getOilPercentage()).orElse(0.0));
            point0200.setIntakeAirTem(Optional.ofNullable(pointProtocol.getIntakeAirTem()).orElse(0));
            point0200.setIntakePressure(Optional.ofNullable(pointProtocol.getIntakePressure()).orElse(0));
            point0200.setCoolingWaterTem(Optional.ofNullable(pointProtocol.getCoolingWaterTem()).orElse(0));
            point0200.setCumulativeRunningTime(Optional.ofNullable(pointProtocol.getCumulativeRunningTime()).orElse(0L));
            point0200.setAmtLoad(Optional.ofNullable(pointProtocol.getAmtLoad()).orElse(0));
            point0200.setVecuLoad(Optional.ofNullable(pointProtocol.getVecuLoad()).orElse(0));

            point0200.setPatch(pointProtocol.getPatch());
            point0200.setDataUpd(pointProtocol.getDataUpd());
            point0200.setSerialNumber(pointProtocol.getSerialNumber());
        }

        return point0200;
    }

    /**
     * 公共轨迹协议转换为Point0F37
     * @param pointProtocol 公共轨迹协议
     * @return Point0F37
     */
    @SuppressWarnings("uncheck")
    public static Point0F37 toPoint0F37(PointProtocol pointProtocol){
        Point0F37 point0F37 = null;

        if(null!=pointProtocol && ProtocolEnum.REALTIME.equals(pointProtocol.getProtocol())){
            point0F37 = new Point0F37();
            point0F37.setTid(pointProtocol.getTid());
            point0F37.setTripId(pointProtocol.getTripId());
            point0F37.setProtocol(pointProtocol.getProtocol());
            point0F37.setGpsTime(pointProtocol.getGpsTime());
            point0F37.setSpeedKmh(pointProtocol.getSpeedKmh());
            point0F37.setOriginalLat(pointProtocol.getOriginalLat());
            point0F37.setOriginalLng(pointProtocol.getOriginalLng());
            point0F37.setLatitude(pointProtocol.getLatitude());
            point0F37.setLongitude(pointProtocol.getLongitude());
            point0F37.setDirection(pointProtocol.getDirection());
            point0F37.setHeight(pointProtocol.getHeight());
            point0F37.setRotation(pointProtocol.getRotation());
            point0F37.setAccPedalPos(pointProtocol.getAccPedalPos());
            point0F37.setClutchSwitch(pointProtocol.getClutchSwitch());
            point0F37.setEngineOutputTorque(pointProtocol.getEngineOutputTorque());
            point0F37.setFuelConsumptionRate(pointProtocol.getFuelConsumptionRate());
            point0F37.setRealTimeOilConsumption(pointProtocol.getRealTimeOilConsumption());
            point0F37.setDataUpd(pointProtocol.getDataUpd());

            point0F37.setBrake(pointProtocol.getBrake());
            point0F37.setAtmosphericTem(Optional.ofNullable(pointProtocol.getAtmosphericTem()).orElse(0));
        }

        return point0F37;
    }

    /**
     * Point0200转换为公共轨迹协议
     * @param point0200 Point0200
     * @return 公共轨迹协议
     */
    public static PointProtocol toPointProtocol(Point0200 point0200){
        PointProtocol pointProtocol = null;
        if(null != point0200){
            pointProtocol = new PointProtocol();
            pointProtocol.setTid(point0200.getTid());
            pointProtocol.setTripId(point0200.getTripId());
            pointProtocol.setProtocol(point0200.getProtocol());
            pointProtocol.setGpsTime(point0200.getGpsTime());
            pointProtocol.setSpeedKmh(point0200.getSpeedKmh());
            pointProtocol.setLatitude(point0200.getLatitude());
            pointProtocol.setLongitude(point0200.getLongitude());
            pointProtocol.setOriginalLat(point0200.getOriginalLat());
            pointProtocol.setOriginalLng(point0200.getOriginalLng());
            pointProtocol.setHeight(point0200.getHeight());
            pointProtocol.setDirection(point0200.getDirection());
            pointProtocol.setRotation(point0200.getRotation());
            pointProtocol.setAccPedalPos(point0200.getAccPedalPos());
            pointProtocol.setClutchSwitch(point0200.getClutchSwitch());
            pointProtocol.setEngineOutputTorque(point0200.getEngineOutputTorque());
            pointProtocol.setFuelConsumptionRate(point0200.getFuelConsumptionRate());
            pointProtocol.setRealTimeOilConsumption(point0200.getRealTimeOilConsumption());

            //0F37特有
            pointProtocol.setBrake(0);
            pointProtocol.setAtmosphericTem(null);

            //0200特有
            pointProtocol.setAccStatus(point0200.getAccStatus());
            pointProtocol.setCurveStatus(point0200.getCurveStatus());
            pointProtocol.setCruiseControl(point0200.getCruiseControl());
            pointProtocol.setHandBrakeStatus(point0200.getHandBrakeStatus());
            pointProtocol.setSharpTurningStatus(point0200.getSharpTurningStatus());
            pointProtocol.setSlideNeutralStatus(point0200.getSlideNeutralStatus());
            pointProtocol.setSlamAcceleratorStatus(point0200.getSlamAcceleratorStatus());
            pointProtocol.setRapidAccelerationStatus(point0200.getRapidAccelerationStatus());
            pointProtocol.setRapidDecelerationStatus(point0200.getRapidDecelerationStatus());

            pointProtocol.setGpsMileage(point0200.getGpsMileage());
            pointProtocol.setEcuMileage(point0200.getEcuMileage());
            pointProtocol.setMeterMileage(point0200.getMeterMileage());
            pointProtocol.setIntegralMileage(point0200.getIntegralMileage());
            pointProtocol.setStandardMileage(point0200.getStandardMileage());
            pointProtocol.setIntegralFuelCons(point0200.getIntegralFuelCons());
            pointProtocol.setStandardFuelCons(point0200.getStandardFuelCons());
            pointProtocol.setTotalFuelCons(point0200.getTotalFuelCons());
            pointProtocol.setOilPercentage(point0200.getOilPercentage());
            pointProtocol.setIntakeAirTem(point0200.getIntakeAirTem());
            pointProtocol.setIntakePressure(point0200.getIntakePressure());
            pointProtocol.setCoolingWaterTem(point0200.getCoolingWaterTem());
            pointProtocol.setCumulativeRunningTime(point0200.getCumulativeRunningTime());
            pointProtocol.setAmtLoad(point0200.getAmtLoad());
            pointProtocol.setVecuLoad(point0200.getVecuLoad());

            pointProtocol.setPatch(point0200.getPatch());
            pointProtocol.setDataUpd(point0200.getDataUpd());
            pointProtocol.setSerialNumber(point0200.getSerialNumber());
        }
        return pointProtocol;
    }

    /**
     * Point0F37转换为公共轨迹协议
     * @param point0F37 Point0F37
     * @return 公共轨迹协议
     */
    public static PointProtocol toPointProtocol(Point0F37 point0F37){
        PointProtocol pointProtocol = null;

        if(null != point0F37){
            pointProtocol = new PointProtocol();
            pointProtocol.setTid(point0F37.getTid());
            pointProtocol.setTripId(point0F37.getTripId());
            pointProtocol.setProtocol(point0F37.getProtocol());
            pointProtocol.setGpsTime(point0F37.getGpsTime());
            pointProtocol.setSpeedKmh(point0F37.getSpeedKmh());
            pointProtocol.setOriginalLat(point0F37.getOriginalLat());
            pointProtocol.setOriginalLng(point0F37.getOriginalLng());
            pointProtocol.setLatitude(point0F37.getLatitude());
            pointProtocol.setLongitude(point0F37.getLongitude());
            pointProtocol.setDirection(point0F37.getDirection());
            pointProtocol.setHeight(point0F37.getHeight());
            pointProtocol.setRotation(point0F37.getRotation());
            pointProtocol.setAccPedalPos(point0F37.getAccPedalPos());
            pointProtocol.setClutchSwitch(point0F37.getClutchSwitch());
            pointProtocol.setEngineOutputTorque(point0F37.getEngineOutputTorque());
            pointProtocol.setFuelConsumptionRate(point0F37.getFuelConsumptionRate());
            pointProtocol.setRealTimeOilConsumption(point0F37.getRealTimeOilConsumption());
            pointProtocol.setDataUpd(point0F37.getDataUpd());
            pointProtocol.setSerialNumber(point0F37.getSerialNumber());

            pointProtocol.setBrake(point0F37.getBrake());
            pointProtocol.setAtmosphericTem(point0F37.getAtmosphericTem());
        }

        return pointProtocol;
    }

    /**
     * 位置PB转化为公共轨迹协议
     * @param locationData 位置点的PB对象
     * @return 公共轨迹协议
     */
    public static PointProtocol toPointProtocol(LCLocationData.LocationData locationData){
        PointProtocol pointProtocol = null;

        if (locationData != null) {
            pointProtocol = new PointProtocol();
            pointProtocol.setTid(locationData.getTerminalId());
            pointProtocol.setProtocol(ProtocolEnum.LOCATION);
            pointProtocol.setGpsTime(locationData.getGpsDate() * 1000);
            pointProtocol.setSpeedKmh(locationData.getElectricVehicle()==0 ? locationData.getSpeed() : locationData.getElectricVehicle()/100.0);
            pointProtocol.setLatitude(locationData.getLatitude());
            pointProtocol.setLongitude(locationData.getLongitude());
            pointProtocol.setOriginalLat(locationData.getOriginalLat());
            pointProtocol.setOriginalLng(locationData.getOriginalLng());
            pointProtocol.setHeight(locationData.getHeight());
            pointProtocol.setDirection(locationData.getDirection());

            pointProtocol.setPatch(locationData.getIsPatch() ? 1 : 0);
            pointProtocol.setSerialNumber(locationData.getSerialNumber());
            pointProtocol.setAmtLoad((int) locationData.getTcuLoad());
            pointProtocol.setVecuLoad((int) locationData.getVecuLoad());
            pointProtocol.setStandardMileage(locationData.getStandardMileage());
            pointProtocol.setStandardFuelCons(locationData.getStandardFuelCon());
            pointProtocol.setGpsMileage(BigDecimalUtils.divide(locationData.getMileage(), 1000, 2).doubleValue());

            //0F37特有，0200为默认值
            pointProtocol.setBrake(0);
            pointProtocol.setAtmosphericTem(null);

            //获取状态位信息
            pointProtocol.setAccStatus(parseStatus(locationData.getStatus(), 0));

            //获取告警位信息
            pointProtocol.setCurveStatus(parseAlarm(locationData.getAlarm(), 15));

            //获取附加状态位信息
            LCLocationData.VehicleStatusAddition statusAddition = locationData.getStatusAddition();
            if(null != statusAddition){
                List<LCVehicleStatusData.VehicleStatusData> statusList = statusAddition.getStatusList();
                if(null != statusList){
                    for (LCVehicleStatusData.VehicleStatusData status : statusList) {
                        long statusValue = status.getStatusValue();
                        switch (status.getTypes().getNumber()) {
                            //公共属性
                            case rotation_VALUE:
                                pointProtocol.setRotation((int) (statusValue / 100));
                                break;
                            case accPedalPos_VALUE:
                                pointProtocol.setAccPedalPos((int) (statusValue / 100));
                                break;
                            case clutchSwitch_VALUE:
                                pointProtocol.setClutchSwitch((int) (statusValue / 100));
                                break;
                            case actualEnginePercentTor_VALUE:
                                pointProtocol.setEngineOutputTorque((int) statusValue / 100);
                                break;
                            case fuelConsumptionRate_VALUE:
                                pointProtocol.setFuelConsumptionRate(statusValue / 100.0 / 1000.0); //发动机燃油消耗率（毫升/小时）转为 L/H
                                break;
                            case realTimeOilConsumption_VALUE:
                                pointProtocol.setRealTimeOilConsumption(statusValue / 100.0);
                                break;
                            case brakeSwitch_VALUE:
                                pointProtocol.setBrake((int) (statusValue / 100));
                                break;

                            //特有属性
                            case cruiseCtrlActive_VALUE:
                                pointProtocol.setCruiseControl((int) statusValue);
                                break;
                            case mileage_VALUE:
                                pointProtocol.setEcuMileage(statusValue / 100.0 );
                                break;
                            case mileageDD_VALUE:
                                pointProtocol.setMeterMileage(statusValue / 100.0 );
                                break;
                            case differentialMileage_VALUE:
                                pointProtocol.setIntegralMileage(statusValue / 100.0 );
                                break;
                            case integralFuelConsumption_VALUE:
                                pointProtocol.setIntegralFuelCons(statusValue / 100.0 );
                                break;
                            case totalFuelConsumption_VALUE:
                                pointProtocol.setTotalFuelCons(statusValue / 100.0 );
                                break;
                            case oilValue_VALUE:
                                double per = statusValue / 100.0 ;
                                if (per >= 0 && per <= 100) {
                                    pointProtocol.setOilPercentage(per);
                                }
                                break;
                            case coolingWaterTem_VALUE:
                                pointProtocol.setCoolingWaterTem((int) statusValue / 100);
                                break;
                            case intakeAirTem_VALUE:
                                pointProtocol.setIntakeAirTem((int) statusValue / 100);
                                break;
                            case dpfPressure_VALUE:
                                pointProtocol.setIntakePressure((int) statusValue / 100);
                                break;
                            case cumulativeRunningTime_VALUE:
                                pointProtocol.setCumulativeRunningTime(statusValue / 100);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }

            //获取附加报警位信息
            ByteString additionAlarm = locationData.getAdditionAlarm();
            if (additionAlarm != null) {
                if (additionAlarm.size() >= 8) {
                    //在第8个字节，字节对应的第2位为手刹状态位
                    pointProtocol.setHandBrakeStatus((additionAlarm.byteAt(7) >> 1) & 0x01);
                }
                if (additionAlarm.size() >= 6) {
                    //在第6个字节
                    byte additionAlarmAt6 = additionAlarm.byteAt(5);
                    //bit0 空挡滑行
                    pointProtocol.setSlideNeutralStatus(additionAlarmAt6 & 0x01);
                    //bit1 急加速
                    pointProtocol.setRapidAccelerationStatus((additionAlarmAt6 >> 1) & 0x01);
                    //bit2 急减速
                    pointProtocol.setRapidDecelerationStatus((additionAlarmAt6 >> 2) & 0x01);
                    //bit3 急转弯
                    pointProtocol.setSharpTurningStatus((additionAlarmAt6 >> 3) & 0x01);
                    //bit6 猛踩油门报警状态
                    pointProtocol.setSlamAcceleratorStatus((additionAlarmAt6 >> 6) & 0x01);
                }
            }
        }

        return pointProtocol;
    }

    /**
     * 密集PB转化为公共轨迹协议
     * @param realTimeData 密集数据的PB对象
     * @return 公共轨迹协议
     */
    public static PointProtocol toPointProtocol(RealTimeDataPb.RealTimeData realTimeData){
        PointProtocol pointProtocol = null;
        if (null != realTimeData) {
            pointProtocol = new PointProtocol();
            pointProtocol.setTid(realTimeData.getTerminalId());
            pointProtocol.setProtocol(ProtocolEnum.REALTIME);
            pointProtocol.setHeight(realTimeData.getHeight());
            pointProtocol.setGpsTime(realTimeData.getGpsTime());
            pointProtocol.setLatitude(realTimeData.getLatitude());
            pointProtocol.setLongitude(realTimeData.getLongitude());
            pointProtocol.setOriginalLat(realTimeData.getOriginalLat());
            pointProtocol.setOriginalLng(realTimeData.getOriginalLng());
            pointProtocol.setSpeedKmh(realTimeData.getSpeed() / 100.0);
            pointProtocol.setRotation(realTimeData.getRotation() / 100);
            pointProtocol.setDirection(realTimeData.getGpsDirection() / 100);
            pointProtocol.setAccPedalPos(realTimeData.getAccelerator() / 100);
            pointProtocol.setClutchSwitch(realTimeData.getClutchSwitch() / 100);
            pointProtocol.setEngineOutputTorque(realTimeData.getEngineOutputTorque() / 100);
            pointProtocol.setFuelConsumptionRate(realTimeData.getFuelConsumptionRate() / 100.0);
            pointProtocol.setRealTimeOilConsumption(realTimeData.getRealTimeOilConsumption() / 100.0);

            pointProtocol.setBrake(realTimeData.getBrake() / 100);
            pointProtocol.setAtmosphericTem(realTimeData.getAtmosphericTemperature() / 100);
        }

        return pointProtocol;
    }

    /**
     * 解析状态位
     * @param status 状态值
     * @param index  取值位
     * @return 解码后的数值
     */
    public static int parseStatus(long status, int index) {
        return (int) ((status & (0x01 << index)) >> index);
    }

    /**
     * 解析告警位
     * @param alarm 告警值
     * @param index 取值位
     * @return 解码后的值
     */
    public static int parseAlarm(long alarm, int index) {
        return (int) ((alarm >> index) & 0x01);
    }

}
